home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume4 / 68kdisassem / part1 next >
Encoding:
Internet Message Format  |  1986-11-30  |  41.9 KB

  1. From: turner@imagen.UUCP <talcott!topaz!Shasta!imagen!Jim.Turner>
  2. Subject: unc - 68000 disassembler
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 4, Issue 30
  7. Submitted by: turner@imagen.UUCP <talcott!topaz!Shasta!imagen!Jim.Turner>
  8.  
  9. #! /bin/sh
  10. # This is a shell archive, meaning:
  11. # 1. Remove everything above the #! /bin/sh line.
  12. # 2. Save the resulting text in a file.
  13. # 3. Execute the file with /bin/sh (not csh) to create the files:
  14. #    README
  15. #    doc
  16. #    doc.out
  17. #    makefile
  18. #    unc.h
  19. #    alloc.c
  20. #    file.c
  21. #    heur.c
  22. # This archive created: Fri Mar 14 09:54:34 1986
  23. export PATH; PATH=/bin:$PATH
  24. echo shar: extracting "'README'" '(806 characters)'
  25. if test -f 'README'
  26. then
  27.     echo shar: will not over-write existing file "'README'"
  28. else
  29. cat << \SHAR_EOF > 'README'
  30. I have gotten many many requests to email this or post it, because of
  31. its size email'ing it screws up most mailers, so i am submitting it to
  32. mod.sources to be posted.  Please note a major cavaet with this, it was
  33. written under Unisoft's port of Unix so the a.out file that it uses
  34. more closely resembles the b.out.h file that most cross assemblers
  35. (e.g.  greenhills) use. For the obvious reasons i have not included that
  36. file with the posting. I did not write this nor do i make any claim to
  37. that effect.
  38.  
  39.     turner@imagen.UUCP <talcott!topaz!Shasta!imagen!Jim.Turner>
  40.  
  41. ----------------------------
  42. This is the 68000 disassembler mentioned on the net.
  43. It is not my final version by any means, but I have found it extremely
  44. useful and it represents several weeks' work.
  45.  
  46.     John Collins. <jmc@inset.UUCP>
  47. SHAR_EOF
  48. if test 806 -ne "`wc -c < 'README'`"
  49. then
  50.     echo shar: error transmitting "'README'" '(should have been 806 characters)'
  51. fi
  52. fi
  53. echo shar: extracting "'doc'" '(6445 characters)'
  54. if test -f 'doc'
  55. then
  56.     echo shar: will not over-write existing file "'doc'"
  57. else
  58. cat << \SHAR_EOF > 'doc'
  59. .\"/*%    nroff -cm -rL72 %|epson|spr -f plain.a -h uncdoc -w
  60. .nr Hb 7
  61. .nr Hs 3
  62. .ds HF 3 3 3 3 3 3 3
  63. .nr Hu 5
  64. .nr Hc 1
  65. .SA 1
  66. .PH "''A Disassembler''"
  67. .PF "'Issue %I%'- Page \\\\nP -'%G%'"
  68. .H 1 "Introduction"
  69. This document describes the first release of a disassembler for UNIX
  70. executable files.
  71. The key features are:
  72. .AL
  73. .LI
  74. For object files the output can be assembled to generate the same
  75. object module, (apart from minor variations in symbol table ordering) as the
  76. input.
  77. .LI
  78. For stripped executable files object modules and libraries may be scanned,
  79. modules in the main input identified and the appropriate names automatically
  80. inserted into the output.
  81. .LI
  82. An option is available to convert most non-global names into local symbols,
  83. which cuts down the symbols in the generated assembler file.
  84. .LI
  85. The disassembler copes reasonably with modules merged with the
  86. .B "-r"
  87. option to
  88. .B "ld" ,
  89. generating a warning message as to the number of modules involved.
  90. .LE
  91. .P
  92. At present this is available for certain Motorola 68000 ports of UNIX
  93. System III and System V. Dependencies on
  94. .AL a
  95. .LI
  96. Instruction set.
  97. .LI
  98. Object module format.
  99. .LI
  100. Library module format.
  101. .LI
  102. Assembler output format.
  103. .LE
  104. .P
  105. are hopefully sufficiently localised to make the product useful as a
  106. basis for other disassemblers for other versions of UNIX.
  107. .P
  108. The product is thus distributed in source form at present.
  109. .H 1 "Use"
  110. The disassembler is run by entering:
  111. .DS I
  112. unc mainfile lib1 lib2 ...
  113. .DE
  114. .P
  115. The first named file is the file to be disassembled, which should be
  116. a single file, either an object module, a (possibly stripped) executable
  117. file, or a library member. Library members are designated using a
  118. parenthesis notation, thus:
  119. .DS I
  120. unc '/lib/libc.a(printf.o)'
  121. .DE
  122. .P
  123. It is usually necessary to escape the arguments in this case to prevent
  124. misinterpretation by the shell. Libraries in standard places such as
  125. .I "/lib"
  126. and
  127. .I "/usr/lib"
  128. may be specified in the same way as to
  129. .B "ld" ,
  130. thus
  131. .DS I
  132. unc '-lc(printf.o)'
  133. unc '-lcurses(wmove.o)'
  134. .DE
  135. .P
  136. As an additional facility, the list of directories searched for
  137. libraries may be varied by setting the environment variable
  138. .B "LDPATH" ,
  139. which is interpreted similarly to the shell
  140. .B "PATH"
  141. variable, and of course defaults to
  142. .DS I
  143. LDPATH=/lib:/usr/lib
  144. .DE
  145. .P
  146. As a further facility, the insertion of
  147. .B "lib"
  148. before and
  149. .B ".a"
  150. after the argument may be suppressed by using a capital
  151. .B "-L"
  152. argument, thus to print out the assembler for
  153. .I "/lib/crt0.o" ,
  154. then the command
  155. .DS I
  156. unc -Lcrt0.o
  157. .DE
  158. .P
  159. should have the desired effect.
  160. .P
  161. Second and subsequent file arguments are only referenced for stripped
  162. executable files, and may consist of single object files and library
  163. members, using the same syntax as before, or whole libraries of object
  164. files, thus:
  165. .DS I
  166. unc strippedfile -Lcrt0.o -lcurses -ltermcap '-lm(sqrt.o)' -lc
  167. .DE
  168. .P
  169. It is advisable to make some effort to put the libraries to be searched
  170. in the order in which they were originally loaded. This is because the
  171. search for each module starts where the previously matched module ended.
  172. However, no harm is done if this rule is not adhered to apart from
  173. increased execution time except in the rare cases where the disassembler
  174. is confused by object modules which are very nearly similar.
  175. .H 1 "Additional options"
  176. The following options are available to modify the behaviour of the
  177. disassembler.
  178. .VL 15 2
  179. .LI "-o file"
  180. Causes output to be sent to the specified file instead of the standard
  181. output.
  182. .LI "-t prefix"
  183. Causes temporary files to be created with the given prefix. The default
  184. prefix is
  185. .B "split" ,
  186. thus causing two temporary files to be created with this prefix in the
  187. current directory. If it is desired, for example, to create the files as
  188. .B "/tmp/xx*" ,
  189. then the argument
  190. .B "-t /tmp/xx"
  191. should be given. Note that the temporary files may be very large as a
  192. complete map of the text and data segments is generated.
  193. .LI "-a"
  194. Suppresses the generation of non-global absolute symbols from the
  195. output. This saves output from C compilations without any obvious
  196. problems, but the symbols are by default included in the name of
  197. producing as nearly identical output as possible to the original source.
  198. .LI "-s"
  199. Causes an additional scan to take place where all possible labels are
  200. replaced by local symbols. The local symbols are inserted in strictly
  201. ascending order, starting at 1.
  202. .LI "-v"
  203. Causes a blow-by-blow account of activities to be output on the standard
  204. error.
  205. .LE
  206. .H 1 "Diagnostics etc"
  207. Truncated or garbled object and library files usually cause processing
  208. to stop with an explanatory message.
  209. .P
  210. The only other kinds of message are some passing warnings concerning
  211. obscure constructs not handled, such as the relocation of byte fields,
  212. or the relocation of overlapping fields. Occasionally a message
  213. .DS I
  214. Library clash: message
  215. .DE
  216. .P
  217. may appear and processing cease. This message is found where at a late
  218. stage in processing libraries, the program discovers that due to the
  219. extreme similarity of two or more library members, it has come to the
  220. wrong conclusion about which one to use. The remedy here is to spell out
  221. to the program which members to take in which order.
  222. .H 1 "Future development"
  223. In the future it is hoped to devise ways of making the disassembler
  224. independent of all the above-mentioned version dependencies, by first
  225. reading a files defining these things. This will probably be applied
  226. after the Common Object Format becomes more standard.
  227. .P
  228. In the long term it would be desirable and useful to enhance the product
  229. to produce compilable C in addition to assemblable assembler. Stages in
  230. the process are seen as follows:
  231. .AL
  232. .LI
  233. Better identification of basic blocks in the code. Switch statements are
  234. a major problem here, as are constant data held in the text segment.
  235. .LI
  236. Marrying of data to the corresponding text. It is in various places hard
  237. to divorce static references "on the fly" (e.g. strings, and switch
  238. lists in some implementations) from static at the head of a module. This
  239. is part of the problem of identifying basic blocks.
  240. .LI
  241. Compilation of header files to work out structure references within the
  242. text. At this stage some interaction may be needed.
  243. .LE
  244. .P
  245. Meanwhile the product is one which is a useful tool to the author in its
  246. present form. Comments and suggestions as to the most practical method
  247. of improving the product in the ways suggested or in other ways would be
  248. gratefully considered.
  249. SHAR_EOF
  250. if test 6445 -ne "`wc -c < 'doc'`"
  251. then
  252.     echo shar: error transmitting "'doc'" '(should have been 6445 characters)'
  253. fi
  254. fi
  255. echo shar: extracting "'doc.out'" '(7415 characters)'
  256. if test -f 'doc.out'
  257. then
  258.     echo shar: will not over-write existing file "'doc.out'"
  259. else
  260. cat << \SHAR_EOF > 'doc.out'
  261.  
  262.  
  263.  
  264.                        A Disassembler
  265.  
  266.  
  267.  
  268.                       1.  Introduction
  269.  
  270. This document describes the first release of a  disassembler
  271. for UNIX executable files.  The key features are:
  272.  
  273.   1.  For object  files  the  output  can  be  assembled  to
  274.       generate  the  same  object  module, (apart from minor
  275.       variations in symbol table ordering) as the input.
  276.  
  277.   2.  For  stripped  executable  files  object  modules  and
  278.       libraries  may  be  scanned, modules in the main input
  279.       identified and  the  appropriate  names  automatically
  280.       inserted into the output.
  281.  
  282.   3.  An option is  available  to  convert  most  non-global
  283.       names  into local symbols, which cuts down the symbols
  284.       in the generated assembler file.
  285.  
  286.   4.  The disassembler copes reasonably with modules  merged
  287.       with the -r option to ld, generating a warning message
  288.       as to the number of modules involved.
  289.  
  290. At present this is  available  for  certain  Motorola  68000
  291. ports of UNIX System III and System V. Dependencies on
  292.  
  293.   a.  Instruction set.
  294.  
  295.   b.  Object module format.
  296.  
  297.   c.  Library module format.
  298.  
  299.   d.  Assembler output format.
  300.  
  301. are hopefully sufficiently localised  to  make  the  product
  302. useful as a basis for other disassemblers for other versions
  303. of UNIX.
  304.  
  305. The product is thus distributed in source form at present.
  306.  
  307.  
  308.                           2.  Use
  309.  
  310. The disassembler is run by entering:
  311.  
  312.      unc mainfile lib1 lib2 ...
  313.  
  314. The first named file is the file to be  disassembled,  which
  315. should  be  a  single  file,  either  an  object  module,  a
  316. (possibly stripped) executable file, or  a  library  member.
  317. Library members are designated using a parenthesis notation,
  318. thus:
  319.  
  320.  
  321.  
  322.                                                       Page 1
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.                        A Disassembler
  331.  
  332.  
  333.  
  334.      unc '/lib/libc.a(printf.o)'
  335.  
  336. It is usually necessary to escape the arguments in this case
  337. to  prevent  misinterpretation  by  the  shell. Libraries in
  338. standard places such as /lib and /usr/lib may  be  specified
  339. in the same way as to ld, thus
  340.  
  341.      unc '-lc(printf.o)'
  342.      unc '-lcurses(wmove.o)'
  343.  
  344. As an additional facility, the list of directories  searched
  345. for  libraries  may  be  varied  by  setting the environment
  346. variable LDPATH, which is interpreted similarly to the shell
  347. PATH variable, and of course defaults to
  348.  
  349.      LDPATH=/lib:/usr/lib
  350.  
  351. As a further facility, the insertion of lib  before  and  .a
  352. after  the  argument may be suppressed by using a capital -L
  353. argument, thus to print out the assembler  for  /lib/crt0.o,
  354. then the command
  355.  
  356.      unc -Lcrt0.o
  357.  
  358. should have the desired effect.
  359.  
  360. Second and subsequent file arguments are only referenced for
  361. stripped  executable files, and may consist of single object
  362. files and library members, using the same syntax as  before,
  363. or whole libraries of object files, thus:
  364.  
  365.      unc strippedfile -Lcrt0.o -lcurses -ltermcap '-lm(sqrt.o)' -lc
  366.  
  367. It is advisable to make some effort to put the libraries  to
  368. be  searched  in  the  order  in  which they were originally
  369. loaded. This is because the search for  each  module  starts
  370. where the previously matched module ended.  However, no harm
  371. is done if this rule is not adhered to apart from  increased
  372. execution   time   except   in  the  rare  cases  where  the
  373. disassembler is confused by object modules  which  are  very
  374. nearly similar.
  375.  
  376.  
  377.                    3.  Additional options
  378.  
  379. The following options are available to modify the  behaviour
  380. of the disassembler.
  381.  
  382.   -o file      Causes output to be  sent  to  the  specified
  383.                file instead of the standard output.
  384.  
  385.  
  386.  
  387.  
  388.                                                       Page 2
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.                        A Disassembler
  397.  
  398.  
  399.  
  400.   -t prefix    Causes temporary files to be created with the
  401.                given  prefix.  The  default prefix is split,
  402.                thus  causing  two  temporary  files  to   be
  403.                created  with  this  prefix  in  the  current
  404.                directory. If it is desired, for example,  to
  405.                create   the  files  as  /tmp/xx*,  then  the
  406.                argument -t /tmp/xx  should  be  given.  Note
  407.                that the temporary files may be very large as
  408.                a complete map of the text and data  segments
  409.                is generated.
  410.  
  411.   -a           Suppresses  the  generation   of   non-global
  412.                absolute  symbols from the output. This saves
  413.                output  from  C  compilations   without   any
  414.                obvious  problems,  but  the  symbols  are by
  415.                default included in the name of producing  as
  416.                nearly  identical  output  as possible to the
  417.                original source.
  418.  
  419.   -s           Causes an additional scan to take place where
  420.                all  possible  labels  are  replaced by local
  421.                symbols. The local symbols  are  inserted  in
  422.                strictly ascending order, starting at 1.
  423.  
  424.   -v           Causes a blow-by-blow account  of  activities
  425.                to be output on the standard error.
  426.  
  427.  
  428.                     4.  Diagnostics etc
  429.  
  430. Truncated or garbled object and library files usually  cause
  431. processing to stop with an explanatory message.
  432.  
  433. The only other kinds of message are  some  passing  warnings
  434. concerning  obscure  constructs  not  handled,  such  as the
  435. relocation of byte fields, or the relocation of  overlapping
  436. fields. Occasionally a message
  437.  
  438.      Library clash: message
  439.  
  440. may appear and processing cease. This message is found where
  441. at  a  late  stage  in  processing  libraries,  the  program
  442. discovers that due to the extreme similarity of two or  more
  443. library  members,  it has come to the wrong conclusion about
  444. which one to use. The remedy here is to  spell  out  to  the
  445. program which members to take in which order.
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.                                                       Page 3
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.                        A Disassembler
  463.  
  464.  
  465.  
  466.                    5.  Future development
  467.  
  468. In the future it is hoped  to  devise  ways  of  making  the
  469. disassembler  independent of all the above-mentioned version
  470. dependencies,  by  first  reading  a  files  defining  these
  471. things.  This  will  probably  be  applied  after the Common
  472. Object Format becomes more standard.
  473.  
  474. In the long term it would be desirable and useful to enhance
  475. the   product   to  produce  compilable  C  in  addition  to
  476. assemblable assembler. Stages in the  process  are  seen  as
  477. follows:
  478.  
  479.   1.  Better identification of basic  blocks  in  the  code.
  480.       Switch  statements  are  a  major problem here, as are
  481.       constant data held in the text segment.
  482.  
  483.   2.  Marrying of data to the corresponding text. It  is  in
  484.       various  places  hard to divorce static references "on
  485.       the fly" (e.g.  strings,  and  switch  lists  in  some
  486.       implementations)  from static at the head of a module.
  487.       This is part  of  the  problem  of  identifying  basic
  488.       blocks.
  489.  
  490.   3.  Compilation of header  files  to  work  out  structure
  491.       references   within  the  text.  At  this  stage  some
  492.       interaction may be needed.
  493.  
  494. Meanwhile the product is one which is a useful tool  to  the
  495. author  in  its present form. Comments and suggestions as to
  496. the most practical method of improving the  product  in  the
  497. ways   suggested  or  in  other  ways  would  be  gratefully
  498. considered.
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.                                                       Page 4
  521.  
  522.  
  523.  
  524.  
  525. SHAR_EOF
  526. if test 7415 -ne "`wc -c < 'doc.out'`"
  527. then
  528.     echo shar: error transmitting "'doc.out'" '(should have been 7415 characters)'
  529. fi
  530. fi
  531. echo shar: extracting "'makefile'" '(128 characters)'
  532. if test -f 'makefile'
  533. then
  534.     echo shar: will not over-write existing file "'makefile'"
  535. else
  536. cat << \SHAR_EOF > 'makefile'
  537. CFLAGS=-v -OB
  538. OBJS=alloc.o file.o libmtch.o robj.o iset.o prin.o heur.o main.o
  539.  
  540. unc:    $(OBJS)
  541.     cc -o unc $(OBJS)
  542.  
  543. $(OBJS):    unc.h
  544. SHAR_EOF
  545. if test 128 -ne "`wc -c < 'makefile'`"
  546. then
  547.     echo shar: error transmitting "'makefile'" '(should have been 128 characters)'
  548. fi
  549. fi
  550. echo shar: extracting "'unc.h'" '(4526 characters)'
  551. if test -f 'unc.h'
  552. then
  553.     echo shar: will not over-write existing file "'unc.h'"
  554. else
  555. cat << \SHAR_EOF > 'unc.h'
  556. /*
  557.  *    SCCS:    @(#)unc.h    1.2    11/2/84    14:21:02
  558.  *    Header file for uncompile program.
  559.  *
  560.  ***********************************************************************
  561.  *    This software is copyright of
  562.  *
  563.  *        John M Collins
  564.  *        47 Cedarwood Drive
  565.  *        St Albans
  566.  *        Herts, AL4 0DN
  567.  *        England            +44 727 57267
  568.  *
  569.  *    and is released into the public domain on the following conditions:
  570.  *
  571.  *        1.  No free maintenance will be guaranteed.
  572.  *        2.  Nothing may be based on this software without
  573.  *            acknowledgement, including incorporation of this
  574.  *            notice.
  575.  *
  576.  *    Notwithstanding the above, the author welcomes correspondence and bug
  577.  *    fixes.
  578.  ***********************************************************************
  579.  */
  580.  
  581. #define    MAXCHARS    50
  582. #define    HASHMOD        97
  583.  
  584. /*
  585.  *    The following structure is used to keep track of symbols.
  586.  */
  587.  
  588. struct    symstr    {
  589.     struct    symstr    *s_next;        /*  Next in hash chain  */
  590.     struct    symstr    *s_link;        /*  Next in duplicate labels */
  591.     unsigned    s_type    :  3;        /*  Symbol type  */
  592.     unsigned    s_newsym:  1;        /*  A new symbol  */
  593.     unsigned    s_invent:  1;        /*  Invented symbol  */
  594.     unsigned    s_glob    :  1;        /*  Global symbol  */
  595.     long        s_value;        /*  Value if defined  */
  596.     short        s_defs;            /*  Defined count  */
  597.     short        s_used;            /*  Used count  */
  598.     unsigned short    s_lsymb;        /*  Local symbol  */
  599.     char        s_name[1];        /*  Chars of name null term */
  600. };
  601.  
  602. typedef    struct    symstr    *symbol;
  603.  
  604. symbol    symbhash[HASHMOD];
  605.  
  606. typedef    struct    {
  607.     int    ef_t;            /*  Text file fd  */
  608.     int    ef_d;            /*  Data file fd  */
  609.     long    ef_entry;        /*  Entry point  */
  610.     long    ef_tsize;        /*  Text size  */
  611.     long    ef_dsize;        /*  Data size  */
  612.     long    ef_bsize;        /*  Bss size  */
  613.     long    ef_end;            /*  End of it all  */
  614.     long    ef_tbase;        /*  Text base  */
  615.     long    ef_dbase;        /*  Data base  */
  616.     long    ef_bbase;        /*  Bss base  */
  617.     int    ef_stcnt;        /*  Number of symbols  */
  618.     int    ef_stmax;        /*  Max number of symbols  */
  619.     symbol    *ef_stvec;        /*  Symbol vector  */
  620. }  ef_fids;
  621.  
  622. typedef    ef_fids    *ef_fid;
  623.  
  624. /*
  625.  *    Description of word in text file.  This entry is held in the place
  626.  *    corresponding to the address in the text file.
  627.  */
  628.  
  629. typedef    struct    {
  630.     unsigned  short    t_contents;        /*  Actual contents  */
  631.     unsigned  short t_iindex;        /*  Index in table  */
  632.     unsigned    t_type    :  2;        /*  Type  */
  633.     unsigned    t_vins  :  1;        /*  Valid instruction  */
  634.     unsigned    t_bdest    :  1;        /*  Is branch dest  */
  635.     unsigned    t_gbdest:  1;        /*  Is global dest  */
  636.     unsigned    t_dref    :  1;        /*  Refered to in data  */
  637.     unsigned    t_bchtyp:  2;        /*  Branch type  */
  638.     unsigned    t_lng    :  3;        /*  Length in words  */
  639.     unsigned    t_reloc :  2;        /*  Relocatable  */
  640.     unsigned    t_rptr    :  2;        /*  Where relocated  */
  641.     unsigned    t_rdisp :  1;        /*  Relocatable displacement */
  642.     unsigned    t_isrel :  1;        /*  Relocated  */
  643.     unsigned    t_amap    :  1;        /*  Worked out  */
  644.     symbol        t_relsymb;        /*  Relocation symbol  */
  645.     long        t_reldisp;        /*  Offset + or - from symb */
  646.     symbol        t_lab;            /*  Label  */
  647.     unsigned  short    t_lsymb;        /*  Local symbol  */
  648.     long        t_reflo;        /*  Lowest place referred  */
  649.     long        t_refhi;        /*  Highest place referred  */
  650.     unsigned  short    t_match;        /*  Lib match lng  */
  651. }  t_entry;
  652.  
  653. /*
  654.  *    Types ......
  655.  */
  656.  
  657. #define    T_UNKNOWN    0
  658. #define    T_BEGIN        1
  659. #define    T_CONT        2
  660.  
  661. #define    R_NONE        0        /*  No relocation  */
  662. #define    R_BYTE        1        /*  Byte relocation  */
  663. #define    R_WORD        2        /*  Word relocation  */
  664. #define    R_LONG        3        /*  Long relocation  */
  665.  
  666. /*
  667.  *    Branch types.
  668.  */
  669.  
  670. #define    T_NOBR        0
  671. #define    T_CONDBR    1
  672. #define    T_UNBR        2
  673. #define    T_JSR        3
  674.  
  675. typedef    struct    {
  676.     unsigned  char    d_contents;        /*  Actual contents  */
  677.     unsigned    d_type  :  4;        /*  Data type  */
  678.     unsigned    d_reloc :  2;        /*  Relocatable  */
  679.     unsigned    d_rptr    :  2;        /*  Where relocated  */
  680.     short        d_lng;            /*  Length -ve for D_CONT */
  681.     symbol        d_relsymb;        /*  Relocation symbol  */
  682.     long        d_reldisp;        /*  Offset + or - from symb */
  683.     symbol        d_lab;            /*  Label  */
  684. }  d_entry;
  685.  
  686. /*
  687.  *    Data types.
  688.  */
  689.  
  690. #define    D_ASC        0        /*  Ascii chars  */
  691. #define    D_ASCZ        1        /*  Null-term ascii  */
  692. #define    D_BYTE        2        /*  Decimal bytes  */
  693. #define    D_WORD        3        /*  Words  */
  694. #define    D_LONG        4        /*  Longs  */
  695. #define    D_ADDR        5        /*  Address pointer  */
  696. #define    D_CONT        6        /*  Continuation of last  */
  697.  
  698. /*
  699.  *    'Common' items.
  700.  */
  701.  
  702. struct    commit    {
  703.     symbol    *c_symb;        /*  List of symbols  */
  704.     int    c_int;            /*  Current number  */
  705.     int    c_max;            /*  Maximum  */
  706. };
  707.  
  708. /*
  709.  *    Library file description.
  710.  */
  711.  
  712. struct    libit    {
  713.     int    lf_fd;            /*  File descriptor  */
  714.     long    lf_offset;        /*  Offset of current file  */
  715.     long    lf_next;        /*  Offset of next file  */
  716.     char    lf_name[14];        /*  Name of item  */
  717. };
  718. SHAR_EOF
  719. if test 4526 -ne "`wc -c < 'unc.h'`"
  720. then
  721.     echo shar: error transmitting "'unc.h'" '(should have been 4526 characters)'
  722. fi
  723. fi
  724. echo shar: extracting "'alloc.c'" '(6396 characters)'
  725. if test -f 'alloc.c'
  726. then
  727.     echo shar: will not over-write existing file "'alloc.c'"
  728. else
  729. cat << \SHAR_EOF > 'alloc.c'
  730. /*
  731.  *    SCCS:    @(#)alloc.c    1.2    11/2/84    14:17:20
  732.  *    Allocate space etc.
  733.  *
  734.  ***********************************************************************
  735.  *    This software is copyright of
  736.  *
  737.  *        John M Collins
  738.  *        47 Cedarwood Drive
  739.  *        St Albans
  740.  *        Herts, AL4 0DN
  741.  *        England            +44 727 57267
  742.  *
  743.  *    and is released into the public domain on the following conditions:
  744.  *
  745.  *        1.  No free maintenance will be guaranteed.
  746.  *        2.  Nothing may be based on this software without
  747.  *            acknowledgement, including incorporation of this
  748.  *            notice.
  749.  *
  750.  *    Notwithstanding the above, the author welcomes correspondence and bug
  751.  *    fixes.
  752.  ***********************************************************************
  753.  */
  754.  
  755. #include <stdio.h>
  756. #include <a.out.h>
  757. #include <setjmp.h>
  758. #include "unc.h"
  759.  
  760. #define    STINC    10
  761.  
  762. char    *malloc(), *realloc();
  763. char    *strncpy();
  764. void    gette(), getde(), setde(), putte(), putde();
  765. void    unimpl();
  766. long    gettw();
  767.  
  768. ef_fids    mainfile;
  769.  
  770. /*
  771.  *    Oops! out of memory.....
  772.  */
  773.  
  774. void    nomem()
  775. {
  776.     (void) fprintf(stderr, "Sorry - run out of memory\n");
  777.     exit(255);
  778. }
  779.  
  780. /*
  781.  *    Look up hash value of symbol.
  782.  */
  783.  
  784. unsigned  shash(str)
  785. register  char    *str;
  786. {
  787.     register  unsigned  result = 0;
  788.     register  int    cnt = 0;
  789.     
  790.     while  (*str  &&  cnt < MAXCHARS)  {
  791.         result += *str++;
  792.         cnt++;
  793.     }
  794.     return  result % HASHMOD;
  795. }
  796.  
  797. /*
  798.  *    Look up hash value of symbol, possibly allocating a new symbol.
  799.  */
  800.  
  801. symbol    lookup(str)
  802. char    *str;
  803. {
  804.     register  symbol  res, *pp;
  805.     register  int    len;
  806.     
  807.     pp = &symbhash[shash(str)];
  808.     res = *pp;
  809.     while  (res != NULL)  {
  810.         if  (strncmp(res->s_name, str, MAXCHARS) == 0)
  811.             return    res;
  812.         pp = &res->s_next;
  813.         res = *pp;
  814.     }
  815.     for  (len = 0;  len < MAXCHARS;  len++)
  816.         if  (str[len] == '\0')
  817.             break;
  818.     len++;
  819.     res = (symbol) malloc(sizeof(struct symstr) + len);
  820.     if  (res == NULL)
  821.         nomem();
  822.     *pp = res;
  823.     res->s_next = NULL;
  824.     (void) strncpy(res->s_name, str, len);
  825.     res->s_name[len] = '\0';        /*  Null-terminate  */
  826.     res->s_newsym = 1;
  827.     res->s_glob = 0;
  828.     res->s_invent = 0;
  829.     res->s_link = NULL;
  830.     res->s_used = 0;
  831.     res->s_defs = 0;
  832.     res->s_lsymb = 0;
  833.     return  res;
  834. }
  835.  
  836. /*
  837.  *    Invent a symbol, making sure that we don't know it.
  838.  */
  839.  
  840. symbol    inventsymb(prefix)
  841. char    *prefix;
  842. {
  843.     static    int  nsymb = 0;
  844.     char    schars[10];
  845.     register  symbol  res;
  846.     
  847.     do    (void) sprintf(schars, "%s%d", prefix, ++nsymb);
  848.     while  (!(res = lookup(schars))->s_newsym);
  849.     
  850.     res->s_newsym = 0;
  851.     res->s_invent = 1;
  852.     return    res;
  853. }
  854.      
  855. /*
  856.  *    Reallocate symbol table.
  857.  */
  858.  
  859. void    reallst(outf)
  860. register  ef_fid  outf;
  861. {
  862.     outf->ef_stmax += STINC;
  863.     if  (outf->ef_stvec == NULL)
  864.         outf->ef_stvec = (symbol *) malloc(outf->ef_stmax * sizeof(symbol));
  865.     else
  866.         outf->ef_stvec = (symbol *) realloc(outf->ef_stvec,
  867.                     outf->ef_stmax * sizeof(symbol));
  868.     if  (outf->ef_stvec == NULL)
  869.         nomem();
  870. }
  871.  
  872. /*
  873.  *    Search through existing symbol table for symbol with given
  874.  *    value.  Invent a new one if needed.
  875.  */
  876.  
  877. symbol    getnsymb(fid, seg, pos)
  878. register  ef_fid  fid;
  879. unsigned  seg;
  880. long    pos;
  881. {
  882.     register  int    i;
  883.     register  symbol  res;
  884.     
  885.     /***********  MACHINE DEPENDENT  ******************************
  886.      *    Convert relocation segment type (argument) to symbol type
  887.      *    (as remembered in symbol table).  Don't ask me why they
  888.      *    have to be different.....
  889.      */
  890.     
  891.     seg += TEXT - RTEXT;
  892.     
  893.     /*
  894.      *    See if the reference is to an external symbol.
  895.      *    If so, use that.
  896.      */
  897.     
  898.     for  (i = 0;  i < fid->ef_stcnt;  i++)  {
  899.         res = fid->ef_stvec[i];
  900.         if  (res->s_type == seg  &&  res->s_value == pos)
  901.             return    res;
  902.     }
  903.     
  904.     /*
  905.      *    Invent a symbol and use that.
  906.      */
  907.     
  908.     res = inventsymb("RS");
  909.     if  (fid->ef_stcnt >= fid->ef_stmax)
  910.         reallst(fid);
  911.     fid->ef_stvec[fid->ef_stcnt++] = res;
  912.     res->s_type = seg;
  913.     res->s_value = pos;
  914.     if  (seg == TEXT)  {
  915.         t_entry    tent;
  916.         gette(fid, pos, &tent);
  917.         tent.t_bdest = 1;
  918.         tent.t_lab = res;
  919.         putte(fid, pos, &tent);
  920.     }
  921.     else  if  (seg == DATA  ||  seg == BSS)  {
  922.         d_entry dent;
  923.         getde(fid, pos, &dent);
  924.         dent.d_lab = res;
  925.         putde(fid, pos, &dent);
  926.     }
  927.  
  928.     return    res;
  929. }
  930.  
  931. /*
  932.  *    Assuming address given is in text segment, find its label, or invent
  933.  *    one.  Also set where refered from.
  934.  */
  935.  
  936. symbol    textlab(loc, refpos)
  937. long    loc, refpos;
  938. {
  939.     t_entry    tent;
  940.  
  941.     gette(&mainfile, loc, &tent);
  942.     if  (tent.t_type == T_CONT)
  943.         return    NULL;
  944.     if  (tent.t_lab == NULL)  {
  945.         tent.t_lab = inventsymb("TS");
  946.         tent.t_lab->s_type = TEXT;
  947.         tent.t_lab->s_value = loc;
  948.         tent.t_bdest = 1;
  949.         putte(&mainfile, loc, &tent);
  950.     }
  951.     else
  952.         tent.t_lab->s_used++;
  953.     if  (tent.t_refhi < refpos)  {
  954.         tent.t_refhi = refpos;
  955.         putte(&mainfile, loc, &tent);
  956.     }
  957.     if  (tent.t_reflo > refpos)  {
  958.         tent.t_reflo = refpos;
  959.         putte(&mainfile, loc, &tent);
  960.     }
  961.     return    tent.t_lab;
  962. }
  963.  
  964. /*
  965.  *    Note references to data.
  966.  */
  967.  
  968. void    mkdref(tpos, size)
  969. long    tpos;
  970. unsigned  size;
  971. {
  972.     t_entry    tent;
  973.     d_entry    dent;
  974.     register  symbol  ds;
  975.     int    dchng = 0;
  976.     int    wsize;
  977.     long    dpos;
  978.     
  979.     gette(&mainfile, tpos, &tent);
  980.     if  (tent.t_relsymb != NULL)
  981.         return;
  982.         
  983.     dpos = gettw(&mainfile, tpos, R_LONG);
  984.     if  (dpos < mainfile.ef_dbase  ||  dpos > mainfile.ef_end)
  985.         return;
  986.     
  987.     switch  (size)  {
  988.     default:
  989.         wsize = D_BYTE;
  990.         break;
  991.     case  2:
  992.         wsize = D_WORD;
  993.         break;
  994.     case  4:
  995.         wsize = D_LONG;
  996.         break;
  997.     }
  998.     
  999.     getde(&mainfile, dpos, &dent);
  1000.     if  ((ds = dent.d_lab) == NULL)  {
  1001.         if  (dpos >= mainfile.ef_bbase)  {
  1002.             ds = inventsymb("BS");
  1003.             ds->s_type = BSS;
  1004.         }
  1005.         else  {
  1006.             ds = inventsymb("DS");
  1007.             ds->s_type = DATA;
  1008.         }
  1009.         ds->s_value = dpos;
  1010.         dent.d_lab = ds;
  1011.         dchng++;
  1012.     }
  1013.     else
  1014.         ds->s_used++;
  1015.  
  1016.     if  (dent.d_type != D_BYTE)  {
  1017.         if  (dent.d_type != wsize)  {
  1018.             if  (dent.d_type == D_ADDR)  {
  1019.                 if  (wsize != D_LONG)
  1020.                     unimpl("Addr word usage");
  1021.             }
  1022.             else  if  (dent.d_type > wsize)  {
  1023.                 dchng++;
  1024.                 dent.d_type = wsize;
  1025.                 dent.d_lng = size;
  1026.             }
  1027.         }
  1028.     }
  1029.     else  {
  1030.         dent.d_type = wsize;
  1031.         dent.d_lng = size;
  1032.         dchng++;
  1033.     }
  1034.     if  (dchng)  {
  1035.         putde(&mainfile, dpos, &dent);
  1036.         for  (dchng = 1;  dchng < size; dchng++)
  1037.             setde(&mainfile, dpos+dchng, D_CONT, 1);
  1038.     }
  1039.         
  1040.     tent.t_relsymb = ds;
  1041.     putte(&mainfile, tpos, &tent);
  1042. }
  1043.  
  1044. /*
  1045.  *    Add item to common or abs list.
  1046.  */
  1047.  
  1048. #define    COMINC    10
  1049.  
  1050. void    addit(cp, symb)
  1051. register  struct  commit  *cp;
  1052. symbol    symb;
  1053. {
  1054.     if  (cp->c_int >= cp->c_max)  {
  1055.         cp->c_max += COMINC;
  1056.         if  (cp->c_symb == NULL)
  1057.             cp->c_symb = (symbol *) malloc(COMINC*sizeof(symbol));
  1058.         else
  1059.             cp->c_symb = (symbol *)
  1060.                     realloc(cp->c_symb,
  1061.                         cp->c_max * sizeof(symbol));
  1062.         if  (cp->c_symb == NULL)
  1063.             nomem();
  1064.     }
  1065.     cp->c_symb[cp->c_int++] = symb;
  1066. }
  1067. SHAR_EOF
  1068. if test 6396 -ne "`wc -c < 'alloc.c'`"
  1069. then
  1070.     echo shar: error transmitting "'alloc.c'" '(should have been 6396 characters)'
  1071. fi
  1072. fi
  1073. echo shar: extracting "'file.c'" '(4184 characters)'
  1074. if test -f 'file.c'
  1075. then
  1076.     echo shar: will not over-write existing file "'file.c'"
  1077. else
  1078. cat << \SHAR_EOF > 'file.c'
  1079. /*
  1080.  *    SCCS:    @(#)file.c    1.2    11/2/84    14:17:35
  1081.  *    Various operations on files.
  1082.  *
  1083.  ***********************************************************************
  1084.  *    This software is copyright of
  1085.  *
  1086.  *        John M Collins
  1087.  *        47 Cedarwood Drive
  1088.  *        St Albans
  1089.  *        Herts, AL4 0DN
  1090.  *        England            +44 727 57267
  1091.  *
  1092.  *    and is released into the public domain on the following conditions:
  1093.  *
  1094.  *        1.  No free maintenance will be guaranteed.
  1095.  *        2.  Nothing may be based on this software without
  1096.  *            acknowledgement, including incorporation of this
  1097.  *            notice.
  1098.  *
  1099.  *    Notwithstanding the above, the author welcomes correspondence and bug
  1100.  *    fixes.
  1101.  ***********************************************************************
  1102.  */
  1103.  
  1104. #include <stdio.h>
  1105. #include <a.out.h>
  1106. #include "unc.h"
  1107.     
  1108. long    lseek();
  1109. void    unimpl();
  1110.  
  1111. /*
  1112.  *    Validate addr and get text entry corresponding to it from the given
  1113.  *    file.
  1114.  */
  1115.  
  1116. void    gette(fid, addr, te)
  1117. register  ef_fid  fid;
  1118. register  long    addr;
  1119. t_entry    *te;
  1120. {
  1121.     addr -= fid->ef_tbase;
  1122.     if  (addr < 0  ||  addr > fid->ef_tsize  || (addr & 1) != 0)  {
  1123.         (void) fprintf(stderr, "Invalid text address %lx\n", addr);
  1124.         exit(200);
  1125.     }
  1126.     (void) lseek(fid->ef_t, (long)(addr * sizeof(t_entry)/2), 0);
  1127.     if  (read(fid->ef_t, (char *) te, sizeof(t_entry)) != sizeof(t_entry))  {
  1128.         (void) fprintf(stderr, "Trouble reading text at %lx\n", addr);
  1129.         exit(201);
  1130.     }
  1131. }
  1132.  
  1133. /*
  1134.  *    Store a text entry.
  1135.  */
  1136.  
  1137. void    putte(fid, addr, te)
  1138. register  ef_fid  fid;
  1139. register  long    addr;
  1140. t_entry    *te;
  1141. {
  1142.     addr -= fid->ef_tbase;
  1143.     if  (addr < 0  ||  addr > fid->ef_tsize  ||  (addr & 1) != 0)  {
  1144.         (void) fprintf(stderr, "Invalid text address %lx\n", addr);
  1145.         exit(200);
  1146.     }
  1147.     (void) lseek(fid->ef_t, (long)(addr * sizeof(t_entry)/2), 0);
  1148.     (void) write(fid->ef_t, (char *) te, sizeof(t_entry));
  1149. }
  1150.  
  1151. /*
  1152.  *    Validate addr and get data entry corresponding to it from the given
  1153.  *    file.
  1154.  */
  1155.  
  1156. void    getde(fid, addr, de)
  1157. register  ef_fid  fid;
  1158. register  long    addr;
  1159. d_entry    *de;
  1160. {
  1161.     if  (addr < fid->ef_dbase  ||  addr > fid->ef_end)  {
  1162.         (void) fprintf(stderr, "Invalid data address %lx\n", addr);
  1163.         exit(200);
  1164.     }
  1165.     addr -= fid->ef_dbase;
  1166.     (void) lseek(fid->ef_d, (long)(addr * sizeof(d_entry)), 0);
  1167.     if  (read(fid->ef_d, (char *) de, sizeof(d_entry)) != sizeof(d_entry))  {
  1168.         (void) fprintf(stderr, "Trouble reading data at %lx\n", addr);
  1169.         exit(201);
  1170.     }
  1171. }
  1172.  
  1173. /*
  1174.  *    Store a data entry.
  1175.  */
  1176.  
  1177. void    putde(fid, addr, de)
  1178. register  ef_fid  fid;
  1179. register  long    addr;
  1180. d_entry    *de;
  1181. {
  1182.     if  (addr < fid->ef_dbase  ||  addr > fid->ef_end)  {
  1183.         (void) fprintf(stderr, "Invalid data address %lx\n", addr);
  1184.         exit(200);
  1185.     }
  1186.     addr -= fid->ef_dbase;
  1187.     (void) lseek(fid->ef_d, (long)(addr * sizeof(d_entry)), 0);
  1188.     (void) write(fid->ef_d, (char *) de, sizeof(d_entry));
  1189. }
  1190.  
  1191. /*
  1192.  *    Set type and length of given data entry.
  1193.  */
  1194.  
  1195. void    setde(fid, addr, type, lng)
  1196. ef_fid    fid;
  1197. long    addr;
  1198. unsigned  type;
  1199. int    lng;
  1200. {
  1201.     d_entry    dat;
  1202.  
  1203.     if  (addr > fid->ef_end)
  1204.         return;
  1205.     getde(fid, addr, &dat);
  1206.     if  (type == D_CONT  &&  dat.d_reloc != R_NONE)  {
  1207.         char    obuf[30];
  1208.         (void) sprintf(obuf, "overlapped reloc 0x%x", addr);
  1209.         unimpl(obuf);
  1210.     }
  1211.     dat.d_type = type;
  1212.     dat.d_lng = lng;
  1213.     putde(fid, addr, &dat);
  1214. }
  1215.     
  1216. /*
  1217.  *    Get a word of data file, size as requested.
  1218.  */
  1219.  
  1220. long    getdw(fid, pos, size)
  1221. register  ef_fid  fid;
  1222. long    pos;
  1223. int    size;
  1224. {
  1225.     d_entry    dat;
  1226.     register  long    res;
  1227.     register  int    i, lt;
  1228.     
  1229.     getde(fid, pos, &dat);
  1230.     
  1231.     switch  (size)  {
  1232.     case  R_BYTE:
  1233.         return    dat.d_contents;
  1234.         
  1235.     case  R_LONG:
  1236.         lt = 4;
  1237.         goto  rest;
  1238.         
  1239.     case  R_WORD:
  1240.         lt = 2;
  1241.     rest:
  1242.         res = dat.d_contents;
  1243.         for  (i = 1;  i < lt; i++)  {
  1244.             getde(fid, pos+i, &dat);
  1245.             res = (res << 8) + dat.d_contents;
  1246.         }
  1247.         return    res;
  1248.         
  1249.     default:
  1250.         (void) fprintf(stderr, "Data word size error\n");
  1251.         exit(20);
  1252.     }
  1253.     /*NOTREACHED*/
  1254. }
  1255.  
  1256. /*
  1257.  *    Get a word of text file.
  1258.  */
  1259.  
  1260. long    gettw(fid, pos, size)
  1261. register  ef_fid  fid;
  1262. long    pos;
  1263. int    size;
  1264. {
  1265.     t_entry    tex;
  1266.     long    res;
  1267.     
  1268.     gette(fid, pos, &tex);
  1269.     
  1270.     switch  (size)  {
  1271.     case  R_BYTE:
  1272.         return    tex.t_contents >> 8;
  1273.         
  1274.     case  R_WORD:
  1275.         return    tex.t_contents;
  1276.         
  1277.     case  R_LONG:
  1278.         res = tex.t_contents;
  1279.         gette(fid, pos+2, &tex);
  1280.         return    (res << 16) + tex.t_contents;
  1281.     default:
  1282.         (void) fprintf(stderr, "Text word size error\n");
  1283.         exit(20);
  1284.     }
  1285.     /*NOTREACHED*/
  1286. }
  1287. SHAR_EOF
  1288. if test 4184 -ne "`wc -c < 'file.c'`"
  1289. then
  1290.     echo shar: error transmitting "'file.c'" '(should have been 4184 characters)'
  1291. fi
  1292. fi
  1293. echo shar: extracting "'heur.c'" '(9885 characters)'
  1294. if test -f 'heur.c'
  1295. then
  1296.     echo shar: will not over-write existing file "'heur.c'"
  1297. else
  1298. cat << \SHAR_EOF > 'heur.c'
  1299. /*
  1300.  *    SCCS:    @(#)heur.c    1.2    11/2/84    14:17:46
  1301.  *    Attempt to guess things about the file.
  1302.  *
  1303.  ***********************************************************************
  1304.  *    This software is copyright of
  1305.  *
  1306.  *        John M Collins
  1307.  *        47 Cedarwood Drive
  1308.  *        St Albans
  1309.  *        Herts, AL4 0DN
  1310.  *        England            +44 727 57267
  1311.  *
  1312.  *    and is released into the public domain on the following conditions:
  1313.  *
  1314.  *        1.  No free maintenance will be guaranteed.
  1315.  *        2.  Nothing may be based on this software without
  1316.  *            acknowledgement, including incorporation of this
  1317.  *            notice.
  1318.  *
  1319.  *    Notwithstanding the above, the author welcomes correspondence and bug
  1320.  *    fixes.
  1321.  ***********************************************************************
  1322.  */
  1323.  
  1324. #include <stdio.h>
  1325. #include <a.out.h>
  1326. #include "unc.h"
  1327.  
  1328. #define    INITDAT    256
  1329. #define    INCDAT    128
  1330.  
  1331. #define    STRSCNT    3
  1332. #define    STRECNT    3
  1333.  
  1334. char    *malloc(), *realloc();
  1335.  
  1336. void    gette(), getde(), setde(), putte(), putde();
  1337. void    nomem();
  1338. long    getdw();
  1339. symbol    inventsymb();
  1340.  
  1341. long    endt;
  1342. ef_fids    mainfile;
  1343.  
  1344. /*
  1345.  *    Talk about implemented things.....
  1346.  */
  1347.  
  1348. void    unimpl(msg)
  1349. char    *msg;
  1350. {
  1351.     (void) fprintf(stderr, "Warning: handling of \"%s\" not implemented\n", msg);
  1352. }
  1353.  
  1354. /*
  1355.  *    Return 1 if string char, otherwise 0.
  1356.  */
  1357.  
  1358. int    possstr(x)
  1359. unsigned  x;
  1360. {
  1361.     if  (x >= ' '  &&  x <= '~')
  1362.         return    1;
  1363.     if  (x == '\n'  ||  x == '\t')
  1364.         return    1;
  1365.     return    0;
  1366. }
  1367.  
  1368. /*
  1369.  *    Guess things about data files.
  1370.  */
  1371.  
  1372. void    intudat(fid)
  1373. ef_fid  fid;
  1374. {
  1375.     register  int    i, j;
  1376.     int    lt, input, invcnt;
  1377.     long    offs, soffs, endd;
  1378.     d_entry    fdat;
  1379.     unsigned  char    *inbuf;
  1380.     int    ibsize;
  1381.     
  1382.     inbuf = (unsigned  char *)malloc(INITDAT);
  1383.     if  (inbuf == NULL)
  1384.         nomem();
  1385.     ibsize = INITDAT;
  1386.     
  1387.     offs = fid->ef_dbase;
  1388.     endd = fid->ef_bbase;
  1389.  
  1390.     while  (offs < endd)  {
  1391.         getde(fid, offs, &fdat);
  1392.         if  (fdat.d_type != D_BYTE)  {
  1393.             offs += fdat.d_lng;
  1394.             continue;
  1395.         }
  1396.         
  1397.         /*
  1398.          *    Looks like general data.  Read in as much as possible.
  1399.          */
  1400.         
  1401.         input = 0;
  1402.         soffs = offs;
  1403.         do  {
  1404.             if  (input >= ibsize)  {
  1405.                 ibsize += INCDAT;
  1406.                 inbuf = (unsigned  char *)
  1407.                     realloc((char *)inbuf, (unsigned)ibsize);
  1408.                 if  (inbuf == NULL)
  1409.                     nomem();
  1410.             }
  1411.             inbuf[input++] = fdat.d_contents;
  1412.             offs++;
  1413.             if  (offs >= endd)
  1414.                 break;
  1415.             getde(fid, offs, &fdat);
  1416.         }  while  (fdat.d_type == D_BYTE && fdat.d_lab == NULL);
  1417.         
  1418.         /*
  1419.          *    Now split up the data.
  1420.          */
  1421.         
  1422.         for  (i = 0;  i < input;  )  {
  1423.             
  1424.             /*
  1425.              *    Might be a string.
  1426.              */
  1427.             
  1428.             if  (possstr(inbuf[i]))  {
  1429.                 lt = input;
  1430.                 if  (i + STRSCNT < lt)
  1431.                     lt = i + STRSCNT;
  1432.                 for  (j = i + 1;  j < lt;  j++)  {
  1433.                     if  (inbuf[j] == '\0')
  1434.                         break;
  1435.                     if  (!possstr(inbuf[j]))
  1436.                         goto  notstr;
  1437.                 }
  1438.                 
  1439.                 /*
  1440.                  *    Looks like a string then.
  1441.                  */
  1442.                 
  1443.                 invcnt = 0;
  1444.                 for  (j = i + 1; j < input;  j++)  {
  1445.                     if  (inbuf[j] == '\0')  {
  1446.                         j++;
  1447.                         break;
  1448.                     }
  1449.                     if  (possstr(inbuf[j]))
  1450.                         invcnt = 0;
  1451.                     else  {
  1452.                         invcnt++;
  1453.                         if  (invcnt >= STRECNT)  {
  1454.                             j -= invcnt - 1;
  1455.                             break;
  1456.                         }
  1457.                     }
  1458.                 }
  1459.  
  1460.                 setde(fid,
  1461.                       soffs+i,
  1462.                       (unsigned)(inbuf[j-1]=='\0'?D_ASCZ:D_ASC),
  1463.                       j - i);
  1464.                 for  (i++;  i < j;  i++)
  1465.                     setde(fid, soffs+i, D_CONT, 1); 
  1466.                 continue;
  1467.             }
  1468.  
  1469. notstr:
  1470.             /*
  1471.              *    If on odd boundary, treat as a byte.
  1472.              */
  1473.             
  1474.             if  ((soffs + i) & 1  ||  i + 1 >= input)  {
  1475.                 setde(fid, soffs + i, D_BYTE, 1);
  1476.                 i++;
  1477.                 continue;
  1478.             }
  1479.  
  1480.             /*
  1481.              *    Treat as longs unless not enough.
  1482.              */
  1483.             
  1484.             if  (i + 3 >= input)  {
  1485.                 setde(fid, soffs + i, D_WORD, 2);
  1486.                 setde(fid, soffs + i + 1, D_CONT, -1);
  1487.                 i += 2;
  1488.                 continue;
  1489.             }
  1490.  
  1491.             /*
  1492.              *    Treat as a long but mark changable.
  1493.              */
  1494.             
  1495.             setde(fid, soffs + i, D_LONG, 4);
  1496.             for  (j = 1;  j < 4;  j++)
  1497.                 setde(fid, soffs + i + j, D_CONT, -j);
  1498.             i += 4;
  1499.         }
  1500.     }
  1501.     free((char *)inbuf);
  1502.     
  1503.     /*
  1504.      *    Now zap bss segment.
  1505.      */
  1506.     
  1507.     offs = fid->ef_bbase;
  1508.     endd = fid->ef_end;
  1509.  
  1510.     while  (offs < endd)  {
  1511.         getde(fid, offs, &fdat);
  1512.         if  (fdat.d_type != D_BYTE)  {
  1513.             offs += fdat.d_lng;
  1514.             continue;
  1515.         }
  1516.  
  1517.         soffs = offs;
  1518.         do  {
  1519.             offs++;
  1520.             if  (offs >= endd)
  1521.                 break;
  1522.             getde(fid, offs, &fdat);
  1523.         }  while  (fdat.d_type == D_BYTE && fdat.d_lab == NULL);
  1524.         
  1525.         setde(fid, soffs, D_BYTE, (int)(offs-soffs));
  1526.         for  (i = -1, soffs++;  soffs < offs; i--, soffs++)
  1527.             setde(fid, soffs, D_CONT, i); 
  1528.     }
  1529. }
  1530.  
  1531. /*
  1532.  *    For non relocatable files, try to identify address pointers in
  1533.  *    the data.
  1534.  */
  1535.  
  1536. void    inturdat(fid)
  1537. ef_fid    fid;
  1538. {
  1539.     register  long    offs = fid->ef_dbase;
  1540.     register  int    i;
  1541.     register  symbol  ds;
  1542.     long  endd = fid->ef_bbase;
  1543.     long  cont;
  1544.     d_entry    dent, refdent;
  1545.  
  1546.     while  (offs < endd)  {
  1547.         getde(fid, offs, &dent);
  1548.         if  (dent.d_type != D_LONG)
  1549.             goto  endit;
  1550.         cont = getdw(fid, offs, R_LONG);
  1551.         if  (cont < fid->ef_dbase || cont > fid->ef_end)
  1552.             goto  endit;
  1553.         getde(fid, cont, &refdent);
  1554.         if  (refdent.d_type == D_CONT)  {
  1555.             d_entry    pdent;
  1556.             int    siz;
  1557.             
  1558.             if  (refdent.d_lng >= 0)
  1559.                 goto  endit;
  1560.             getde(fid, cont+refdent.d_lng, &pdent);
  1561.             i = -refdent.d_lng;
  1562.             refdent.d_lng += pdent.d_lng;
  1563.             pdent.d_lng = i;
  1564.             if  (pdent.d_type == D_LONG  &&  i == 2)
  1565.                 siz = D_WORD;
  1566.             else
  1567.                 siz = D_BYTE;
  1568.             refdent.d_type = siz;
  1569.             pdent.d_type = siz;
  1570.             putde(fid, cont - i, &pdent);
  1571.             for  (i = 1;  i < refdent.d_lng;  i++)
  1572.                 setde(fid, cont+i, D_CONT, -i);
  1573.         }
  1574.         if  ((ds = refdent.d_lab) == NULL)  {
  1575.             if  (cont >= fid->ef_bbase)  {
  1576.                 ds = inventsymb("BS");
  1577.                 ds->s_type = BSS;
  1578.             }
  1579.             else  {
  1580.                 ds = inventsymb("DS");
  1581.                 ds->s_type = DATA;
  1582.             }
  1583.             ds->s_value = cont;
  1584.             refdent.d_lab = ds;
  1585.             putde(fid, cont, &refdent);
  1586.         }
  1587.         else
  1588.             ds->s_used++;
  1589.         dent.d_type = D_ADDR;
  1590.         dent.d_relsymb = ds;
  1591.         dent.d_rptr = ds->s_type;
  1592.         putde(fid, offs, &dent);
  1593.         for  (i = 1;  i < 4;  i++)
  1594.             setde(fid, offs+i, D_CONT, 1);
  1595. endit:
  1596.         offs += dent.d_lng;
  1597.     }
  1598. }
  1599.  
  1600. /*
  1601.  *    Recursively follow through the code, stopping at unconditional
  1602.  *    branches and invalid instructions.
  1603.  */
  1604.  
  1605. void    follseq(pos)
  1606. long    pos;
  1607. {
  1608.     t_entry    tent;
  1609.     int    lng;
  1610.     long    npos;
  1611.  
  1612.     while  (pos < endt)  {
  1613.         gette(&mainfile, pos, &tent);
  1614.         if  (tent.t_amap)    /*  Been here  */
  1615.             return;
  1616.         tent.t_amap = 1;
  1617.         lng = findinst(&tent, pos);
  1618.         npos = pos + lng*2;
  1619.         if  (npos > endt)  {
  1620.             tent.t_vins = 0;
  1621.             tent.t_lng = 1;
  1622.             tent.t_type = T_UNKNOWN;
  1623.             lng = 0;
  1624.             npos = endt;
  1625.         }
  1626.         putte(&mainfile, pos, &tent);
  1627.         pos = npos;
  1628.         
  1629.         if  (lng <= 0)
  1630.             return;
  1631.  
  1632.         switch  (tent.t_bchtyp)  {
  1633.         case  T_UNBR:
  1634.             if  (tent.t_relsymb == NULL)
  1635.                 return;
  1636.             pos = tent.t_relsymb->s_value;
  1637.             continue;
  1638.         case  T_JSR:
  1639.             if  (tent.t_relsymb != NULL)
  1640.                 follseq(tent.t_relsymb->s_value);
  1641.             continue;
  1642.         case  T_CONDBR:
  1643.             follseq(tent.t_relsymb->s_value);
  1644.         default:
  1645.             continue;
  1646.         }
  1647.     }
  1648. }
  1649.             
  1650.             
  1651. /*
  1652.  *    Try to work out things about text files.
  1653.  */
  1654.  
  1655. void    intutext()
  1656. {
  1657.     long    pos;
  1658.     t_entry    tent;
  1659.     int    lng;
  1660.     
  1661.     endt = mainfile.ef_tbase + mainfile.ef_tsize;
  1662.     pos = mainfile.ef_entry;
  1663. nextv:
  1664.     for  (;  pos < endt;)  {
  1665.         gette(&mainfile, pos, &tent);
  1666.         if  (!tent.t_amap && tent.t_vins)  {
  1667.             follseq(pos);
  1668.             pos += 2;
  1669.             goto  nextiv;
  1670.         }
  1671.         pos += tent.t_lng * 2;
  1672.         if  (tent.t_bchtyp == T_UNBR)
  1673.             goto  nextiv;
  1674.     }
  1675.     goto    dorest;
  1676. nextiv:
  1677.     for  (;  pos < endt;  pos += 2)  {
  1678.         gette(&mainfile, pos, &tent);
  1679.         if  (tent.t_bdest)
  1680.             goto  nextv;
  1681.     }
  1682. dorest:
  1683.     /*
  1684.      *    Deal with unmapped instructions.
  1685.      */
  1686.     
  1687.     for  (pos = 0;  pos < endt;)  {
  1688.         gette(&mainfile, pos, &tent);
  1689.         switch  (tent.t_type)  {
  1690.         case  T_BEGIN:
  1691.             pos += tent.t_lng * 2;
  1692.             continue;
  1693.         case  T_UNKNOWN:
  1694.             if  (tent.t_vins)  {
  1695.                 lng = findinst(&tent, pos);
  1696.                 putte(&mainfile, pos, &tent);
  1697.                 if  (lng > 0)  {
  1698.                     pos += lng * 2;
  1699.                     continue;
  1700.                 }
  1701.             }
  1702.         default:
  1703.             pos += 2;
  1704.             continue;
  1705.         }
  1706.     }
  1707. }
  1708.  
  1709. /*
  1710.  *    Invent local symbols.
  1711.  */
  1712.  
  1713. void    intlsym()
  1714. {
  1715.     long    bpos, epos, hiref, hipos;
  1716.     unsigned  llnum;
  1717.     t_entry    tent;
  1718.     register  symbol  tl;
  1719.     
  1720.     endt = mainfile.ef_tbase + mainfile.ef_tsize;
  1721.     epos = mainfile.ef_entry;
  1722.     for  (;;)  {
  1723.         bpos = epos;
  1724.         hiref = bpos;
  1725.         if  (epos >= endt)
  1726.             return;
  1727.         gette(&mainfile, epos, &tent);
  1728.         epos += tent.t_lng * 2;
  1729.         for  (;  epos < endt;)  {
  1730.             gette(&mainfile, epos, &tent);
  1731.             if  (tent.t_gbdest  ||  tent.t_dref)
  1732.                 break;
  1733.             if  (tent.t_reflo < bpos)
  1734.                 break;
  1735.             if  (tent.t_refhi > hiref)  {
  1736.                 hiref = tent.t_refhi;
  1737.                 hipos = epos;
  1738.             }
  1739.             epos += tent.t_lng * 2;
  1740.         }
  1741.         if  (hiref > epos)
  1742.             epos = hipos;
  1743.         llnum = 0;
  1744.         for  (hipos = bpos;  hipos < epos;)  {
  1745.             gette(&mainfile, hipos, &tent);
  1746.             if  (!tent.t_gbdest && !tent.t_dref &&
  1747.              tent.t_reflo >= bpos && tent.t_refhi < epos &&
  1748.              (tl = tent.t_lab) != NULL)
  1749.                 tl->s_lsymb = ++llnum;
  1750.             hipos += tent.t_lng * 2;
  1751.         }
  1752.     }
  1753. }
  1754.  
  1755. /*
  1756.  *    Given the main file, a possible candidate for matching in the
  1757.  *    file and an offset, see if text matches.  Return 1 if matches,
  1758.  *    or 0 if no match.
  1759.  */
  1760.  
  1761. int    matchup(mf, lf, startpos)
  1762. register  ef_fid  mf, lf;
  1763. long    startpos;
  1764. {
  1765.     register  int    i, matches = 0;
  1766.     t_entry    ltent, mtent;
  1767.  
  1768.     if  (lf->ef_tsize > mf->ef_tsize - startpos + mf->ef_tbase)
  1769.         return    0;    /*  At end - can't fit  */
  1770.  
  1771.     for  (i = 0;  i < lf->ef_tsize;  i += 2)  {
  1772.         gette(lf, lf->ef_tbase + i, <ent);
  1773.         if  (ltent.t_isrel)
  1774.             continue;
  1775.         gette(mf, startpos + i, &mtent);
  1776.         if  (mtent.t_contents != ltent.t_contents)
  1777.             return    0;
  1778.         matches++;
  1779.     }
  1780.     
  1781.     /*
  1782.      *    Give up on zero length or all relocatable files.
  1783.      */
  1784.     
  1785.     return    matches > 0;
  1786. }
  1787.  
  1788. /*
  1789.  *    Scan through main file looking for a match.
  1790.  */
  1791.  
  1792. long    findstart(mf, lf)
  1793. register  ef_fid  mf, lf;
  1794. {
  1795.     register  long    res = mf->ef_tbase;
  1796.     long    lim = mf->ef_tbase + mf->ef_tsize - lf->ef_tsize;
  1797.     t_entry    tent;
  1798.     
  1799. restart:
  1800.     for  (;  res <= lim;  res += 2)  {
  1801.         gette(mf, res, &tent);
  1802.         if  (tent.t_match != 0)  {
  1803.             res += tent.t_match;
  1804.             goto  restart;
  1805.         }
  1806.         if  (matchup(mf, lf, res))
  1807.             return    res;
  1808.     }
  1809.     return    -1;
  1810. }
  1811.  
  1812. /*
  1813.  *    Mark the head of a matched module to save searching.
  1814.  */
  1815.  
  1816. void    markmatch(mf, lf, pos)
  1817. ef_fid    mf, lf;
  1818. long    pos;
  1819. {
  1820.     t_entry    tent;
  1821.     
  1822.     gette(mf, pos, &tent);
  1823.     tent.t_match = (unsigned) lf->ef_tsize;
  1824.     putte(mf, pos, &tent);
  1825. }
  1826. SHAR_EOF
  1827. if test 9885 -ne "`wc -c < 'heur.c'`"
  1828. then
  1829.     echo shar: error transmitting "'heur.c'" '(should have been 9885 characters)'
  1830. fi
  1831. fi
  1832. exit 0
  1833. #    End of shell archive
  1834.